package model;

import java.awt.image.BufferedImage;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import model.abstracts.Main;
import model.abstracts.UnlockableWithIcon;
import model.abstracts.Writable;
import model.abstracts.WritableWithIcon;
import tools.ImageEditor;
import tools.Tools;

public class Technology extends WritableWithIcon {

    public static final Map<String, Technology> technologies = new HashMap<>();

    public String description;

    public int cost;
    public String era;
    public int treeRow;

    public String boost;

    public List<String> prereqTech = new ArrayList<>();
    public List<String> leadToTech = new ArrayList<>();
    public List<Integer> randomCost = new ArrayList<>();

    public Technology (String tag) {
        super(tag);
        technologies.put(tag, this);
    }

    
    // load technologies from database
    public static void load () {
        Statement gameplay = null;
        try {
            gameplay = DriverManager.getConnection(Tools.GAMEPLAY_DATABASE).createStatement();
    
            // load technologies list
            ResultSet r1 = gameplay.executeQuery("select * from Technologies;");
            while (r1.next()) {
                String tag = r1.getString("TechnologyType");
                Technology technology = new Technology(tag);
                technology.name = r1.getString("Name");
                technology.description = r1.getString("Description");

                technology.cost = r1.getInt("Cost");
                technology.era = r1.getString("EraType");
                technology.treeRow = r1.getInt("UITreeRow");
            }
    
            // load other information
            for(Entry<String, Technology> entry : technologies.entrySet()) {
                String tag = entry.getKey();
                Technology technology = entry.getValue();

                // load prereq technologies
                ResultSet r2 = gameplay.executeQuery("select * from TechnologyPrereqs where Technology = \"" + tag + "\";");
                while (r2.next()) {
                    technology.prereqTech.add(r2.getString("PrereqTech"));
                }

                // load lead to technologies
                ResultSet r3 = gameplay.executeQuery("select * from TechnologyPrereqs where PrereqTech = \"" + tag + "\";");
                while (r3.next()) {
                    technology.leadToTech.add(r3.getString("Technology"));
                }

                // load boost
                ResultSet r4 = gameplay.executeQuery("select * from Boosts where TechnologyType = \"" + tag + "\";");
                if (r4.next()) {
                    technology.boost = r4.getString("TriggerDescription");
                }

                // load random cost
                ResultSet r5 = gameplay.executeQuery("select * from TechnologyRandomCosts where TechnologyType = \"" + tag + "\";");
                while (r5.next()) {
                    technology.randomCost.add(r5.getInt("Cost"));
                }

                // load technology icon
                String iconString = "ICON_" + tag;
                BufferedImage icon = Tools.getImage(iconString);
                if (icon != null) {
                    String path = iconString + ".png";
                    technology.icon = Tools.IMAGE_URL + "/" + path;
                    ImageEditor.saveImage(icon, path);
                }
            }
        } catch (Exception e) {
            System.err.println("Error loading technologis.");
            System.err.println(e.getClass().getName() + e.getMessage());
        } finally {
            try {
                if (gameplay != null) gameplay.close();
            } catch (Exception e) {
            }
        }
    }

    @Override
    public JSONObject toJson(String language) {
        JSONObject object = super.toJson(language);

        JSONArray leftColumnItems = new JSONArray();
        if (description != null) {
            leftColumnItems.add(Tools.getHeader(Tools.getControlText("Description", language)));
            leftColumnItems.add(Tools.getBody("", Tools.getText(description, language)));
        }
        object.put("leftColumnItems", leftColumnItems);

        JSONArray rightColumnItems = new JSONArray();
        object.put("rightColumnItems", rightColumnItems);

        JSONArray traitContents = new JSONArray();
        rightColumnItems.add(Tools.getStatbox(Tools.getControlText("Traits", language), traitContents));

        traitContents.add(Tools.getSeparator());
        traitContents.add(Tools.getHeader(Tools.getControlText("Era", language)));
        traitContents.add(Tools.getLabel(Tools.getText("LOC_" + era + "_NAME", language)));
        if (randomCost.size() == 0) {
            traitContents.add(Tools.getHeader(Tools.getControlText("Science Cost", language)));
            traitContents.add(Tools.getLabel(cost + Tools.getYield("SCIENCE", language)));
        } else {
            traitContents.add(Tools.getHeader(Tools.getControlText("Science Cost", language) + Tools.getControlText(" (Random)", language)));
            for (Integer c : randomCost) {
                traitContents.add(Tools.getLabel(c + Tools.getYield("SCIENCE", language)));
            }
        }

        if (boost != null) {
            traitContents.add(Tools.getHeader(Tools.getControlText("Eureka", language)));
            traitContents.add(Tools.getLabel(Tools.getText(boost, language)));
        }

        JSONArray unlockContents = new JSONArray();
        
        unlockContents.add(Tools.getSeparator());
        List<UnlockableWithIcon> uniques = new ArrayList<>();

        for (Writable o : Main.WRITABLES) {
            if (o instanceof UnlockableWithIcon) {
                UnlockableWithIcon obj = (UnlockableWithIcon) o;
                if (tag.equals(obj.prereqTech)) {
                    boolean isUnique = false;
                    for (Trait trait : Trait.traits.values()) {
                        if(trait.pointsTo != null && trait.pointsTo.equals(obj.tag)) {
                            isUnique = true;
                            break;
                        }
                    }
                    if (!isUnique) {
                        unlockContents.add(obj.getIconLabel(language));
                    } else {
                        uniques.add(obj);
                    }
                }
            }
        }

        if (unlockContents.size() != 1 && uniques.size() > 0) {
            unlockContents.add(Tools.getSeparator());
        }

        for (UnlockableWithIcon obj : uniques) {
            unlockContents.add(obj.getIconLabel(language));
        }

        if (unlockContents.size() != 1) {
            rightColumnItems.add(Tools.getStatbox(Tools.getControlText("Unlocks", language), unlockContents));
        }

        JSONArray treeContents = new JSONArray();
        rightColumnItems.add(Tools.getStatbox(Tools.getControlText("Tech Tree", language), treeContents));

        treeContents.add(Tools.getSeparator());

        if (prereqTech.size() > 0) {
            treeContents.add(Tools.getHeader(Tools.getControlText("Prerequires", language)));
            for (String t : prereqTech) {
                Technology technology = technologies.get(t);
                treeContents.add(technology.getIconLabel(language));
            }
        }

        if (prereqTech.size() > 0 && leadToTech.size() > 0) {
            treeContents.add(Tools.getSeparator());
        }

        if (leadToTech.size() > 0) {
            treeContents.add(Tools.getHeader(Tools.getControlText("Leads To Tech", language)));
            for (String t : leadToTech) {
                Technology technology = Technology.technologies.get(t);
                treeContents.add(technology.getIconLabel(language));
            }
        }
        
        return object;
    }

    @Override
    public String getChapter() {
        return "technologies";
    }

    @Override
    public String getFolder() {
        return era;
    }

	@Override
	public int getFolderOrder() {
		return Era.eras.get(era).chronologyIndex;
	}

    @Override
    public String getFolderName(String language) {
        return Tools.getText("LOC_" + era + "_NAME", language);
    }

    @Override
    public String getTagPrefix() {
        return "TECH_";
    }

    @Override
    public int getOrder() {
        return cost * 8 + treeRow;
    }

    @Override
    public String getCat() {
        return "科技&市政改动";
    }

    @Override
    public int getCatOrder() {
        return -1400;
    }
}
